import React, {memo,useEffect, useRef, useState} from 'react';
import MusicPlayerStyle from "./MusicPlayerStyle";
import {Button, ConfigProvider, Table} from 'antd';
import getLrc from "../../utils/lrcExtract";
import {getHourMineSecondBySecond} from "../../utils/timeFormatting";
import {downloadMp3ByUrl} from "../../utils/download";
import {getRandomRange} from "../../utils/hyRndom";
import {MusicInsertDTO} from "../../interface/MusicInterface";
import {getMusicByIdsApi} from "../../services/music";
import {getMusicId2LocalStorage} from "../../utils/projectFunction";

/**
 * 时间 2024年1月15日 14点26分
 * 关于音乐播放页的介绍
 * 音乐播放页的逻辑和样式可能是整个项目中最复杂的
 * 所以,我们这里先展示不进行代码抽取
 *
 * 这个页面我们可能会对大量元素dom进行操作,
 * 同时也会有许多操作,对于这些操作,我们能封装就封装
 * 能复用就复用,尽量做到定义最少的方法
 */
type Props = {};
/**
 * 这里我们暂时定义一个音乐歌曲对象
 * 具体属性这里我们不再赘述
 *
 */
export default memo(function MusicPlayer(props: Props) {
  const {Column} = Table;
  //audioRef 控制音乐dom的ref
  //注意这里的类型，需要使用原生，所以这里直接定义any
  const audioRef: any = useRef();
  //进度条Ref
  const musicScheduleRef: React.MutableRefObject<any> = useRef();
  //每个歌词的Ref
  const lrcLiRef:React.MutableRefObject<any>=useRef();

  /** 当前被选中的歌曲列表下标 */
  const [currentMusicIndex, setCurrentMusicIndex] = useState(0);
  /** 当前被选中的歌词下标，用于滚动时高速替换 */
  const [currentLrcIndex, setCurrentLrcIndex] = useState(1);
  /** 音乐是否正在播放,默认为false */
  const [musicIsPlay, setMusicIsPlay] = useState(true);
  /** 进度条偏移量 为百分比 */
  const [scheduleOffset, setScheduleOffset] = useState(0);
  /** 音乐音量 为 0 - 1 */
  const [volume,setVolume]=useState(0);
  /** 音乐播放类型，其为 musicSwitchTypeList 数组的下标, 默认为歌单循环*/
  const [musicPlayTypeIndex,setMusicPlayTypeIndex]=useState(0);
  /** 音乐列表，从localStorage中获取*/
  const [musicList,setMusicList]=useState<any>([]);
  /** 当前播放的歌曲类名,用来更新页面 */
  const [currentClassName,setCurrentClassName]=useState("music-lrc-li");
  //歌曲列表
  // let musicList: Array<MusicInsertDTO>=[{name:"",}];
  useEffect(() => {

    //获取本地存储的音乐列表
    getMusicByIdsApi(getMusicId2LocalStorage() as string).then((result:any)=>{
      console.log(result);
      setMusicList(result.data.data);
    },(error)=>{
      console.log(error);
    });
  }, []);

  //复选框改变事件
  function checkOnchange(selectedRowKeys: React.Key[], selectedRows: MusicInsertDTO[]) {
    console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  }

  //歌曲切换类型
  const musicSwitchTypeList=[
    {
      key:1,
      icon:"&#xe6a2;",
      title:"歌单循环",
      clickFunction:function () {
        console.log("歌单循环");
        nextSong();
      }
    },
    {
      key:2,
      icon:"&#xe66d;",
      title:"单曲循环",
      clickFunction:function () {
        console.log("单曲循环");
        audioRef.current.currentTime=0;
        audioRef.current.play();
      }
    },
    {
      key:3,
      icon:"&#xe60e;",
      title:"随机播放",
      clickFunction:function () {
        console.log("随机播放")
        setCurrentMusicIndex(getRandomRange(0,musicList.length-1));
      }
    },
  ];

  /**
   * @type "音乐的播放和暂停事件"
   * @type "传入下标时，进行播放当前下标的音乐"
   * @param index：音乐列表下标
   *
   */
  function musicPlayAndSuspend(index?:number) {
    //index?:Number
    if (index !== undefined) {
      //设置播放的音乐下标
      setCurrentMusicIndex(index);
      //注意播放的一个特殊情况，即单击正在播放歌曲的暂停按钮
      if (index === currentMusicIndex) {
        if (musicIsPlay) {
          audioRef.current.pause();
        } else {
          audioRef.current.play();
        }
        setMusicIsPlay(!musicIsPlay);
      } else {
        setCurrentMusicIndex(index);
        audioRef.current.play();
        // 并且播放
        setMusicIsPlay(true);
      }
    } else {
      if (musicIsPlay) {
        audioRef.current.pause();
      } else {
        audioRef.current.play();
      }
      setMusicIsPlay(!musicIsPlay);
    }
  }

  /** 音乐上一首 */
  function previousSong(): void {
    if (currentMusicIndex <= 0) {
      setCurrentMusicIndex(musicList.length - 1);
      return;
    }
    setCurrentMusicIndex(currentMusicIndex - 1);
  }

  /** 音乐下一首 */
  function nextSong(): void {
    if (currentMusicIndex >= musicList.length - 1) {
      setCurrentMusicIndex(0);
      return;
    }
    //设置audioRef
    setCurrentMusicIndex(currentMusicIndex + 1);
  }



  /** 音乐正在播放的事件
   * 其中包含了一下功能
   * 歌词滚动
   * 进度条变化
   * 时间变化
   * 歌曲播放类型
   *
   *
   * */
  useEffect(() => {
    // setMusicIsPlay(audioRef.current)
    //获取所有歌词的li
    const musicLcLiList: any = document.querySelectorAll(".music-lrc-li");
    //获取滚动的盒子,用于歌词显示在中间
    const musicLrcUl: any = document.querySelector(".music-lrc-ul");

    /** 音乐dom播放事件 */
    audioRef?.current?.addEventListener("timeupdate", function (event: any) {
      /**
       * 歌曲播放时
       * 高亮当前行
       * 这里我们还是使用原生吧
       * */
      //先将播放时间复制给react,进行全局的控制
      setCurrentLrcIndex(parseInt(event.target.currentTime));
      //设置进度条偏移量
      // setScheduleOffset(Math.floor(event.target.currentTime/event.target.duration)*100);
      const value = (parseInt(event.target.currentTime) / event.target.duration) * 100;
      if (value >= 0 && value <= 100) {
        setScheduleOffset(value);
      }
      //获取匹配到的歌词id
      const currentDocument: any = document.getElementById(parseInt(event.target.currentTime) + "");
      //如果存在
      if (currentDocument) {
        for (let i = 0; i < musicLcLiList.length; i++) {
          musicLcLiList[i].className = "music-lrc-li";
        }
        currentDocument.className = "current-music-lrc-li";
        //设置盒子的top值
        musicLrcUl.style.top = `${-currentDocument.offsetTop + 140}px`;
      }
    });

    /** 音乐dom播放结束事件 */
    audioRef?.current?.addEventListener("ended",function () {
      // musicSwitchTypeList[musicPlayTypeIndex].clickFunction();
      nextSong();
    });
    // audioRef.current.onEnded=musicSwitchTypeList[musicPlayTypeIndex].clickFunction();

  }, [audioRef,lrcLiRef]);


  /**
   * 进度条单击事件
   * 使用offsetLeft获取距离页面左边距
   *
   * @param event
   */
  function scheduleClickFun(event: any) {
    //实际偏移量,为了美观,我们给进度条上面封装了两个div盒子,所以实际的偏移量时自身left和父盒子的left
    const realityOffsetLeft=musicScheduleRef.current.offsetLeft+musicScheduleRef.current.offsetParent.offsetLeft;
    //音乐播放条盒子的宽度,我们在css样式种设置的为 800px
    const musicScheduleBoxWidth=musicScheduleRef.current.offsetWidth
    //鼠标单击时,距离音乐播放条盒子的偏移量
    const playedWidth=event.clientX-realityOffsetLeft;
    const b=playedWidth/musicScheduleBoxWidth;
    // @ts-ignore
    audioRef.current.currentTime=audioRef.current.duration*b;
  }

  /** 音量单击事件 */
  function changeVolume():void{
    if (volume===1){
      setVolume(0);
      // audioRef.current.volume=volume
    }else{
      setVolume(1);
    }
    audioRef.current.volume=volume;
  }

  /** 歌曲循环类型切换 */
  function changeMusicPlayType() {
    if (musicPlayTypeIndex>=musicSwitchTypeList.length-1){
      setMusicPlayTypeIndex(0);
    }else{
      setMusicPlayTypeIndex(musicPlayTypeIndex+1);
    }
    /** 音乐dom播放结束事件 */
    audioRef.current?.addEventListener("ended",function () {
      musicSwitchTypeList[musicPlayTypeIndex].clickFunction();
    });
  }
  // return(<></>);
  return (
    <MusicPlayerStyle>
      {/*// @ts-ignore*/}
      <video className="audio-tag" style={{display:"none"}} autoPlay src={musicList[currentMusicIndex]?.url} ref={audioRef}></video>

      {/*蒙版*/}
      <div className="music-box-bg" style={{backgroundImage: `url(${musicList[currentMusicIndex]?.cover})`}}></div>
      <div className="music-box-mask"></div>

      {/*用户中心*/}
      <div className="music-user-box"></div>

      {/*音乐主体盒子*/}
      <div className="music-content-box">
        <div className="music-content-left">
          <div className="music-player-btn-box">
            <Button className="iconfont music-player-btn">&#xe86f; 收藏</Button>
            <Button className="iconfont music-player-btn">&#xe604; 添加到</Button>
            <Button className="iconfont music-player-btn">&#xe606; 下载</Button>
            <Button className="iconfont music-player-btn">&#xe718; 删除</Button>
            <Button className="iconfont music-player-btn">&#xe62f; 清空列表</Button>
          </div>
          {/**对于音乐表格的配置我们这里说一下
           我们不使用分页的形式,而是采用滚动的方式
           columns={columns}
           */}
          <ConfigProvider
            theme={{
              components: {
                Table:{
                  headerBg:"transparent",
                  headerColor:"#FFFFFF",
                  rowSelectedBg:"transparent",
                  footerColor:"#FFFFFF",
                  fontSize:18
                }
              }
            }}
          >
            <Table
              className="music-table"
              pagination={false}
              rowSelection={{onChange: checkOnchange}}
              dataSource={musicList as any}
              scroll={{y: 600}}
            >
              <Column title="歌曲名称"
                      key="name"
                      render={(_: any, musicItem: MusicInsertDTO, index) => (
                        <>
                          {
                            /** 判断说明：
                             *  当前正在播放的 index 和 当前是否正在播放
                             * */
                            index === currentMusicIndex && musicIsPlay ?
                              <span className="playing-gif-image"></span> : <></>
                          }
                          <span>{musicItem?.name}</span>
                        </>

                      )}
              />
              <Column title="歌手" dataIndex="singerName" key="singerName"/>
              <Column title="时长"
                      render={(value, musicItem: MusicInsertDTO, index) => {
                        return (<span>{getHourMineSecondBySecond(musicItem?.timer as number)}</span>)
                      }}
              />
              <Column
                title="操作"
                render={(_: any, musicItem: MusicInsertDTO, index) => {
                  return (
                    <>
                      <Button
                        onClick={() => {
                          musicPlayAndSuspend(index)
                        }}
                      >{index === currentMusicIndex && musicIsPlay ? "暂停" : "播放"}</Button>
                      <Button>删除</Button>
                    </>
                  )
                }}
              />
            </Table>
          </ConfigProvider>
        </div>
        {/*音乐右边,歌词与封面*/}
        <div className="music-content-right">
          {/*这里的界面我们直接仿qq,不再使用网易云的了*/}
          <div className="music-cover-image"
               style={{backgroundImage: `url(${musicList[currentMusicIndex]?.cover})`}}
          ></div>
          <div className="music-right-name">歌曲名: <span>{musicList[currentMusicIndex]?.name}</span></div>
          <div className="music-right-name">歌手: <span>{musicList[currentMusicIndex]?.singerName}</span></div>
          <div className="music-right-name">专辑: <span>{musicList[currentMusicIndex]?.albumName}</span></div>
          {/*  最主要的部分了,歌词*/}
          <div className="music-lrc-box">
            <ul className="music-lrc-ul">
              {/*  这里我们暂时使用li*/}
              {/*className={currentLrcIndex===item?.timer?"music-lrc-li current-music-lrc-li":"music-lrc-li"}*/}
              {
                getLrc(musicList[currentMusicIndex]?.lyric as string).map((item, index) => {
                  return (<li
                    id={item?.timer + ""}
                    className="music-lrc-li"
                    key={index}
                    ref={lrcLiRef}>
                    {item?.content}
                  </li>)
                })
              }
            </ul>
          </div>

        </div>


      </div>

      {/*音乐控制台盒子*/}
      <div className="music-console-box">
        <div className="music-console-content">
          {/*上一首*/}
          <span className="iconfont" onClick={previousSong}>&#xe78a;</span>
          {/*播放和暂停*/}
          <span className="iconfont"
                onClick={() => {
                  musicPlayAndSuspend()
                }}
                dangerouslySetInnerHTML={{__html: musicIsPlay ? "&#xea81;" : "&#xe87c;"}}
          ></span>
          {/*下一首*/}
          <span className="iconfont" onClick={nextSong}>&#xe7a5;</span>
          <div className="console-message-box">
            <div className="console-message-top-box">
              {/*音乐名称*/}
              <div>
                <span className="music-console-name">{musicList[currentMusicIndex]?.name}</span>
                --
                <span className="singer-console-name">{musicList[currentMusicIndex]?.singerName}</span>
              </div>

              <div>
                {/*音乐已经播放的时长*/}
                <span className="music-timied">{getHourMineSecondBySecond(currentLrcIndex)} </span>
                /
                {/*音乐总时长*/}
                <span
                  className="music-timer"> {getHourMineSecondBySecond(musicList[currentMusicIndex]?.timer as number)}</span>
              </div>

            </div>
            <div onClick={(event) => {
              scheduleClickFun(event)
            }}
                 ref={musicScheduleRef}
                 className="console-message-bottom-box">
              {/*进度条小圆点*/}
              <div style={{left: `${scheduleOffset}%`}} className="music-schedule-btn"></div>
              {/*进度条已经播放的长度*/}
              <div style={{width: `${scheduleOffset}%`}} className="music-schedule-line"></div>
            </div>

          </div>
          {/*音乐播放类型,有三种*/}
          <span className="player-type-btn iconfont"
                onClick={changeMusicPlayType}
                title={musicSwitchTypeList[musicPlayTypeIndex].title}
                dangerouslySetInnerHTML={{__html: musicSwitchTypeList[musicPlayTypeIndex].icon}}
          ></span>
          {/*是否收藏*/}
          <span className="music-collect iconfont">&#xe86f;</span>
          {/*下载*/}
          <span className="music-collect iconfont" onClick={()=>{
            downloadMp3ByUrl(musicList[currentMusicIndex]?.url as string,musicList[currentMusicIndex]?.name)
          }}>&#xe606;</span>
          {/*评论*/}
          <span className="music-collect iconfont">&#xe891;</span>
          {/*  不再写纯净模式*/}
          {/*  音量*/}
          <span className="music-volume iconfont"
                dangerouslySetInnerHTML={{__html: volume ? "&#xe65e;" : "&#xe8c1;"}}
                onClick={()=>{
                  changeVolume()
                }}
               ></span>
        </div>


      </div>
    </MusicPlayerStyle>
  );
});
